package com.wx.spider.common.util;

import java.io.*;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author:feng
 * @create:2021-04-25 16:02
 * 从html 当中提取 字符集
 */
public class CharactorSetExtractor {

    // public static String DEFAULT_ENCODE = "gbk";

    // private static CharsetDetector charsetDetector = new CharsetDetector();

    public static void main(String args[]) throws UnsupportedEncodingException {
        CharSequence s = new String(
                "meta http-equiv=\"Content-Type\" content=\"text/html; charset=Big5\"><script src=\"./test_files/ckepop.js\" charset=\"utf-8\"");
        System.out.println(extract(s, ""));
    }

    //

    static Pattern p = Pattern.compile("meta.*?charset\\s*=[\\s'\"]*([\\w-]+)",
            Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);

    private static HashMap<String, String> encode_cache = new HashMap<String, String>();

    /**
     * Maybe the returnValue is null
     *
     * @param url
     * @param input
     * @param defaultEncode
     * @return
     */
    public static String extract(String url, CharSequence input,
                                 String defaultEncode) {
        // String host = com.fi.crawl.util.HostUtil.getHost(url);
        // encode_cache.get(host)
        String encode = null;
        if (encode == null) {
            synchronized (encode_cache) {
                try {
                    encode = extract(input, defaultEncode);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                // if (encode != null) {
                // encode_cache.put(host, encode);
                // }
            }
        }
        return encode;
    }

    public static String extract(File document) {
        String encoding = null;// DEFAULT_ENCODE charset=gb2312 charset=utf-8
        Charset cs = null;
        BufferedReader bufferReader = null;
        try {
            bufferReader = new BufferedReader(new InputStreamReader(
                    new FileInputStream(document)));
            String temp = null;
            while ((temp = bufferReader.readLine()) != null) {
                Matcher m = p.matcher(temp);
                if (m.find()) {
                    encoding = m.group(1);
                    cs = Charset.forName(encoding);
                    break;
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bufferReader != null) {
                try {
                    bufferReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return encoding;
    }

    private static Pattern gbPattern = Pattern.compile("gb");

    public static String extract(CharSequence input, String defaultEncode)
            throws UnsupportedEncodingException {
        String encoding = defaultEncode;// charset=gb2312 charset=utf-8
        if (input == null)
            return defaultEncode;
        Charset cs = null;
        try {

            Matcher m = p.matcher(input);
            if (m.find()) {
                encoding = m.group(1);
                cs = Charset.forName(encoding);
            }
        } catch (Exception e) {
            e.printStackTrace();
            if (gbPattern.matcher(encoding).find()) {
                encoding = "gbk";
            }
        }
        if (encoding == null)
            encoding = defaultEncode;
        // 判断一个编码是否为常见的编码，或者编码转换
        if (encoding != null) {
            String temp = encodeMap.get(encoding.toLowerCase());
            if (temp != null)
                encoding = temp;
        }
        return encoding;
    }

    private static Map<String, String> encodeMap = new HashMap<String, String>();
    {
        encodeMap.put("gb2312", "gbk");
        encodeMap.put("utf8", "utf-8");
        encodeMap.put("utf-8s", "utf-8");
        encodeMap.put("g2312", "gbk");
        encodeMap.put("gb-2312", "gbk");
        encodeMap.put("bg2312", "gbk");
        encodeMap.put("gbk2312", "gbk");
        encodeMap.put("x-gbk", "gbk");
    }

    // finally {
    // if (cs == null) {
    // byte[] bytes = input.toString().getBytes();
    // InputStream in = new ByteArrayInputStream(bytes);
    // cs = charsetDetector.someMethod(new BufferedInputStream(in));
    // if (cs != null) {
    // encoding = cs.toString();
    // }
    // }
    // }
    /*
     * Java代码 Java下系统变量总结：
     *
     * java.version Java 运行时环境版本 java.vendor Java 运行时环境供应商 java.vendor.url Java
     * 供应商的 URL java.home Java 安装目录 java.vm.specification.version Java 虚拟机规范版本
     * java.vm.specification.vendor Java 虚拟机规范供应商 java.vm.specification.name
     * Java 虚拟机规范名称 java.vm.version Java 虚拟机实现版本 java.vm.vendor Java 虚拟机实现供应商
     * java.vm.name Java 虚拟机实现名称 java.specification.version Java 运行时环境规范版本
     * java.specification.vendor Java 运行时环境规范供应商 java.specification.name Java
     * 运行时环境规范名称 java.class.version Java 类格式版本号 java.class.path Java 类路径
     * java.library.path 加载库时搜索的路径列表 java.io.tmpdir 默认的临时文件路径 java.compiler 要使用的
     * JIT 编译器的名称 java.ext.dirs 一个或多个扩展目录的路径 os.name 操作系统的名称 os.arch 操作系统的架构
     * os.version 操作系统的版本 file.separator 文件分隔符（在 UNIX 系统中是“/”） path.separator
     * 路径分隔符（在 UNIX 系统中是“:”） line.separator 行分隔符（在 UNIX 系统中是“/n”） user.name
     * 用户的账户名称 user.home 用户的主目录 user.dir 用户的当前工作目录 file.encoding
     */

    public static String gbk2utf8(String chenese)
            throws UnsupportedEncodingException {
        byte[] fullByte = gbk2utf_8(chenese);
        String fullStr = new String(fullByte, "UTF-8");
        return fullStr;
    }

    private static byte[] gbk2utf_8(String chenese) {
        char c[] = chenese.toCharArray();
        byte[] fullByte = new byte[3 * c.length];
        for (int i = 0; i < c.length; i++) {
            int m = (int) c[i];
            String word = Integer.toBinaryString(m);

            StringBuffer sb = new StringBuffer();
            int len = 16 - word.length();

            for (int j = 0; j < len; j++) {
                sb.append("0");
            }
            sb.append(word);
            sb.insert(0, "1110");
            sb.insert(8, "10");
            sb.insert(16, "10");

            String s1 = sb.substring(0, 8);
            String s2 = sb.substring(8, 16);
            String s3 = sb.substring(16);

            byte b0 = Integer.valueOf(s1, 2).byteValue();
            byte b1 = Integer.valueOf(s2, 2).byteValue();
            byte b2 = Integer.valueOf(s3, 2).byteValue();
            byte[] bf = new byte[3];
            bf[0] = b0;
            fullByte[i * 3] = bf[0];
            bf[1] = b1;
            fullByte[i * 3 + 1] = bf[1];
            bf[2] = b2;
            fullByte[i * 3 + 2] = bf[2];

        }
        return fullByte;
    }

}

